//
//  ScanViewController.m
//  翼安保
//
//  Created by duzhi on 2024/4/25.
//

#import "ScanViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface ScanViewController ()<AVCaptureMetadataOutputObjectsDelegate,AVCaptureVideoDataOutputSampleBufferDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>
//扫描框
@property (nonatomic, strong) UIView * view_bg;
//扫描线
@property (nonatomic, strong) CALayer * layer_scanLine;
//提示语
@property (nonatomic, strong) UILabel * lab_word;
@property (nonatomic, strong) NewsBigButton * lightButton;
@property (nonatomic, strong) NewsBigButton * photoButton;

//采集的设备
@property (strong,nonatomic) AVCaptureDevice * device;
//设备的输入
@property (strong,nonatomic) AVCaptureDeviceInput * input;
//输出
@property (strong,nonatomic) AVCaptureMetadataOutput * output;
//
@property (nonatomic, strong) AVCaptureVideoDataOutput *videoDataOutput;
//采集流
@property (strong,nonatomic) AVCaptureSession * session;
//窗口
@property (strong,nonatomic) AVCaptureVideoPreviewLayer * previewLayer;

@end

@implementation ScanViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NewsBigButton *backButton = [NewsBigButton new];
    [backButton setBackgroundImage:[UIImage imageNamed:@"back_white_26x26"] forState:0];
    [backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:backButton];
    [backButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(relativeWidth(15));
        make.centerY.mas_equalTo(self.view.mas_top).offset(kiPhoneX_Top_Height+22);
    }];
    [self startScan];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.navigationController.navigationBar.hidden = YES;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.navigationController.navigationBar.hidden = NO;
}

- (void)back {
    [self.session stopRunning];
    [self.navigationController popViewControllerAnimated:NO];
}

- (void)dealloc {
    [self.session stopRunning];
}

#pragma mark - add subviews

- (void)addSubviews {
    [self.view addSubview:self.view_bg];
    [self.view addSubview:self.lab_word];
    [self.view addSubview:self.photoButton];
    [self.view addSubview:self.lightButton];
    [self.view_bg.layer addSublayer:self.layer_scanLine];
}

#pragma mark - make constraints

- (void)makeConstraintsForUI {
    [_view_bg mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(CGSizeMake(0.7 * ScreenWidth,  0.7 * ScreenWidth));
        make.centerX.centerY.mas_equalTo(0);
    }];
    
    [_lab_word mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.mas_equalTo(0);
        make.top.mas_equalTo(_view_bg.mas_bottom).with.offset(relativeWidth(20));
    }];
    
    [self.photoButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.mas_equalTo(relativeWidth(-20));
        make.bottom.mas_equalTo(relativeWidth(-15)-kiPhoneX_Bottom_Height);
        make.height.width.mas_equalTo(relativeWidth(33));
    }];
    
    [self.lightButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.mas_equalTo(self.photoButton.mas_left).offset(relativeWidth(-20));
        make.centerY.mas_equalTo(self.photoButton);
        make.height.width.mas_equalTo(relativeWidth(33));
    }];
    
}

#pragma mark - start saomiao

- (void)startScan {
    
    // Device 实例化设备   //获取摄像设备
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    // Input 设备输入     //创建输入流
    _input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:nil];
    
    // Output 设备的输出  //创建输出流
    _output = [[AVCaptureMetadataOutput alloc]init];
    
    //设置代理   在主线程里刷新
    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    // Session         //初始化链接对象
    _session = [[AVCaptureSession alloc]init];
    
    //高质量采集率
    [_session setSessionPreset:AVCaptureSessionPresetHigh];
    
    if ([_session canAddInput:self.input])
    {
        [_session addInput:self.input];
    }
    
    if ([_session canAddOutput:self.output])
    {
        [_session addOutput:self.output];
    }
    
    // 创建摄像数据输出流并将其添加到会话对象上,  --> 用于识别光线强弱
      self.videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
      [_videoDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
      [_session addOutput:_videoDataOutput];
    
    
    //设置扫码支持的编码格式(如下设置条形码和二维码兼容)
    // 二维码类型 AVMetadataObjectTypeQRCode
    _output.metadataObjectTypes =@[AVMetadataObjectTypeCode128Code,AVMetadataObjectTypeUPCECode,AVMetadataObjectTypeCode39Code,AVMetadataObjectTypeCode39Mod43Code,AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code,AVMetadataObjectTypeCode93Code,AVMetadataObjectTypePDF417Code,AVMetadataObjectTypeQRCode,AVMetadataObjectTypeAztecCode,AVMetadataObjectTypeInterleaved2of5Code,AVMetadataObjectTypeITF14Code,AVMetadataObjectTypeDataMatrixCode];
    
    // Preview 扫描窗口设置
    _previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    
    _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    
    _previewLayer.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
    
    //如需限制扫描框范围，打开下一句注释代码并进行相应调整
//    _output.rectOfInterest = CGRectMake(0.05, 0.2, 0.7, 0.6);
    
    [self.view.layer insertSublayer:_previewLayer atIndex:0];
    
    //添加框和线
    [self addSubviews];
    
    [self makeConstraintsForUI];
    [self scanLineMove];
    
    dispatch_async(dispatch_queue_create(0, 0), ^{
        // Start 开始扫描   //开始捕获
        [self.session startRunning];
    });
    
    
}


#pragma - click
- (void)clickLight:(UIButton *)button {
    button.selected = !button.selected;
    if(button.selected) {
        AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
                NSError *error = nil;
                if ([captureDevice hasTorch]) {
                    BOOL locked = [captureDevice lockForConfiguration:&error];
                    if (locked) {
                        captureDevice.torchMode = AVCaptureTorchModeOn;
                        [captureDevice unlockForConfiguration];
                    }
                }
    }else {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)),                  dispatch_get_main_queue(), ^{
                     AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
                     if ([device hasTorch]) {
                           [device lockForConfiguration:nil];
                           [device setTorchMode: AVCaptureTorchModeOff];
                           [device unlockForConfiguration];
                     }
               });

    }
}

- (void)clickPhoto {
    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
    imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    imagePicker.delegate = self;
    [self presentViewController:imagePicker animated:YES completion:nil];

}

#pragma mark - timer action

- (void)scanLineMove {
    
    CABasicAnimation * animation = [[CABasicAnimation alloc] init];
    
    //告诉系统要执行什么样的动画
    animation.keyPath = @"position";
    
    //设置通过动画  layer从哪到哪
    animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
    
    animation.toValue = [NSValue valueWithCGPoint:CGPointMake(0, 0.7 * ScreenWidth)];
    
    //动画时间
    animation.duration = 4.0;
    
    animation.autoreverses = YES;
    animation.repeatCount = CGFLOAT_MAX;
    
    
    //设置保存动画的最新动态
    animation.fillMode = kCAFillModeForwards;
    
    //添加动画到layer
    [self.layer_scanLine addAnimation:animation forKey:nil];
    
}


#pragma mark - UIImagePickerControllerDelegateDelegate
/// 返回一张不超过屏幕尺寸的 image
- (UIImage *)LY_imageSizeWithScreenImage:(UIImage *)image {
    CGFloat imageWidth = image.size.width;
    CGFloat imageHeight = image.size.height;
    CGFloat screenWidth = ScreenWidth-20;
    CGFloat screenHeight = ScreenHeight-kiPhoneX_Top_Height-kiPhoneX_Bottom_Height;
    
    if (imageWidth <= screenWidth && imageHeight <= screenHeight) {
        return image;
    }
    
    CGFloat max = MAX(imageWidth, imageHeight);
    CGFloat scale = max / (ScreenWidth-20);
    
    CGSize size = CGSizeMake(imageWidth / scale, imageHeight / scale);
    UIGraphicsBeginImageContext(size);
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return newImage;
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info {
    // 对选取照片的处理，如果选取的图片尺寸过大，则压缩选取图片，否则不作处理
       UIImage *image = [self LY_imageSizeWithScreenImage:info[UIImagePickerControllerOriginalImage]];
       // CIDetector(CIDetector可用于人脸识别)进行图片解析，从而使我们可以便捷的从相册中获取到二维码
       // 声明一个 CIDetector，并设定识别类型 CIDetectorTypeQRCode
       CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}];
       
       // 取得识别结果
       NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];
       
       if (features.count == 0) {
           [MBProgressHUD showTextHUD:@"识别失败"];
           [self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
       } else {
           NSString *resultStr = @"";
           for (int index = 0; index < [features count]; index ++) {
               CIQRCodeFeature *feature = [features objectAtIndex:index];
               resultStr = feature.messageString;
               NSLog(@"相册中读取二维码数据信息 - - %@", resultStr);
               //               self.detectorString = resultStr;
           }
           [self.presentedViewController dismissViewControllerAnimated:YES completion:^{
               [self.navigationController popViewControllerAnimated:NO];
               if (self.scanViewControllerFinishBlock) {
                   self.scanViewControllerFinishBlock(resultStr);
               }
           }];
       }
}

#pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    // 这个方法会时时调用，但内存很稳定
    CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL,sampleBuffer, kCMAttachmentMode_ShouldPropagate);
    NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict];
    CFRelease(metadataDict);
    NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];
    float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue];
//   if (brightnessValue < - 1) {
//       self.lightButton.hidden = NO;
//    } else {
//       self.lightButton.hidden = YES;
//    }
}



#pragma mark - AVCaptureMetadataOutputObjects delegate

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    
    //得到解析到的结果
    NSString * stringValue;
    
    if (metadataObjects.count > 0) {
        
        AVMetadataMachineReadableCodeObject * metadataObject = metadataObjects.firstObject;
        
        stringValue = metadataObject.stringValue;
    }
    NSLog(@"相册中读取二维码数据信息 - - %@", stringValue);
    //停止扫描
    [_session stopRunning];
    [self.navigationController popViewControllerAnimated:NO];
    if (self.scanViewControllerFinishBlock) {
        self.scanViewControllerFinishBlock(stringValue);
    }
}

#pragma mark - setter and getter

- (UIView *)view_bg {
    
    if (!_view_bg) {
        
        _view_bg = [[UIView alloc] init];
        
        _view_bg.layer.borderColor = [UIColor whiteColor].CGColor;
        
        _view_bg.layer.borderWidth = 2.0;
    }
    
    return _view_bg;
}

- (CALayer *)layer_scanLine {
    
    if (!_layer_scanLine) {
        
        CALayer * layer = [[CALayer alloc] init];
        
        layer.bounds = CGRectMake(0, 0, 0.7 * ScreenWidth, 1);
        
        layer.backgroundColor = [UIColor greenColor].CGColor;

        //起点
        layer.position = CGPointMake(0, 0);
        
        //定位点
        layer.anchorPoint = CGPointMake(0, 0);
        
        _layer_scanLine = layer;
    }
    
    return _layer_scanLine;
}

- (UILabel *)lab_word {
    
    if (!_lab_word) {
        
        _lab_word = [[UILabel alloc] init];
        
        _lab_word.textAlignment = NSTextAlignmentCenter;
        
        _lab_word.textColor = [UIColor whiteColor];
        
        _lab_word.font = [UIFont systemFontOfSize:relativeWidth(14)];
        
        _lab_word.text = @"将二维码/条码放入框内，即可进行扫描";
    }
    
    return _lab_word;
}

- (NewsBigButton *)lightButton {
    if(!_lightButton){
        _lightButton = [NewsBigButton new];
        [_lightButton setBackgroundImage:[UIImage imageNamed:@"shoudiantong"] forState:0];
//        [_lightButton setTitle:@"打开手电筒" forState:0];
//        [_lightButton setTitle:@"关闭手电筒" forState:UIControlStateSelected];
        [_lightButton setTitleColor:[UIColor whiteColor] forState:0];
        _lightButton.titleLabel.font = [UIFont boldSystemFontOfSize:relativeWidth(16)];
        [_lightButton addTarget:self action:@selector(clickLight:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _lightButton;
}

- (NewsBigButton *)photoButton {
    if(!_photoButton){
        _photoButton = [NewsBigButton new];
        [_photoButton setBackgroundImage:[UIImage imageNamed:@"xiangce"] forState:0];
//        [_photoButton setTitle:@"打开相册" forState:0];
        [_photoButton setTitleColor:[UIColor whiteColor] forState:0];
        _photoButton.titleLabel.font = [UIFont boldSystemFontOfSize:relativeWidth(16)];
        [_photoButton addTarget:self action:@selector(clickPhoto) forControlEvents:UIControlEventTouchUpInside];
    }
    return _photoButton;
}

@end
